package org.itboys.core.service.mysql.front;

import org.itboys.commons.ErrorException;
import org.itboys.commons.utils.tools.ListUtil;
import org.itboys.core.common.ExceptionEnum;
import org.itboys.core.common.SundayCommonConstants;
import org.itboys.core.common.UserTypeEnum;
import org.itboys.core.common.WalletRecordEnum;
import org.itboys.core.dao.order.SundaySendOrderModelMapper;
import org.itboys.core.dao.order.SundaySendOrderTrayMapper;
import org.itboys.core.dao.tray.SundayTrayMapper;
import org.itboys.core.dro.order.SundaySendOrderDro;
import org.itboys.core.dro.order.SundaySendOrderModelDro;
import org.itboys.core.dto.order.SundaySendOrderDto;
import org.itboys.core.entity.mongo.SundayMember;
import org.itboys.core.entity.mongo.SundayStore;
import org.itboys.core.entity.mysql.coupon.SundayCoupon;
import org.itboys.core.entity.mysql.order.SundaySendOrder;
import org.itboys.core.entity.mysql.order.SundaySendOrderModel;
import org.itboys.core.entity.mysql.order.SundaySendOrderTray;
import org.itboys.core.entity.mysql.tray.SundayTray;
import org.itboys.core.entity.mysql.tray.SundayTrayModel;
import org.itboys.core.entity.mysql.wallet.SundayWallet;
import org.itboys.core.service.mongo.web.SundayMemberService;
import org.itboys.core.service.mongo.web.SundayOrderFailRecordService;
import org.itboys.core.service.mongo.web.SundayStoreService;
import org.itboys.core.service.mysql.web.SundayTrayModelService;
import org.itboys.core.util.DatetUtil;
import org.itboys.core.util.DistanceUtils;
import org.itboys.core.util.NumberUtil;
import org.itboys.core.util.jxUtil.MapUtil;
import org.itboys.mysql.service.BaseMySqlService;
import org.itboys.param.ParamUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 作者：zzq
 * 时间：2018/12/10
 * 描述：派送订单
 */
@Service
public class SundayFrontSendOrderService extends BaseMySqlService<SundaySendOrder> {
    @Autowired
    private SundayMemberService memberService;
    @Autowired
    private SundayTrayModelService modelService;
    @Autowired
    private SundaySendOrderModelMapper orderModelMapper;
    @Autowired
    private SundayFrontSendOrderModelService orderModelService;
    @Autowired
    private SundayTrayMapper trayMapper;
    @Autowired
    private SundaySendOrderTrayMapper orderTrayMapper;
    @Autowired
    private SundayStoreService storeService;
    @Autowired
    private SundayFrontWalletService walletService;
    @Autowired
    private SundayFrontWalletRecordService walletRecordService;
    @Autowired
    private SundayOrderFailRecordService orderFailRecordService;
    @Autowired
    private SundayFrontCouponService couponService;

    public SundaySendOrderDto findOne(Long orderId) {
        return packageSingleDto(super.find(orderId), null);
    }

    public List<SundaySendOrderDto> selectOrders(HttpServletRequest request, Long memberId, Integer status) {
        Map<String, Object> param = ParamUtil.packageMysqlPageParam(request, "orderNo");
        SundayMember member = memberService.getById(memberId);
        if (member.getUserType() == UserTypeEnum.SUPPLIER.getCode()) {
            param.put("serviceId", memberId);
        } else {
            param.put("memberId", memberId);
        }
        if (status != 0) {
            param.put("status", status);
        }
        List<SundaySendOrder> orders = super.select(param);
        return packageMultiDto(orders);
    }

    /**
     * 创建派送订单
     *
     * @param orderDro
     * @return
     */
    @Transactional
    public SundaySendOrderDto createOrder(Long memberId, SundaySendOrderDro orderDro) throws ParseException {
        logger.info(orderDro.toString());
        SundayMember member = memberService.getById(memberId);
        //匹配配送仓库  供应商
        Long sendCityId = orderDro.getSendCityId();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("isDeleted", SundayCommonConstants.NO);
        param.put("cityId", sendCityId);
        List<SundayStore> stores = storeService.list(param);
        //匹配回收仓库
        param.clear();
        param.put("isDeleted", SundayCommonConstants.NO);
        param.put("cityId", orderDro.getRecycleCityId());
        if (ListUtil.isNull(storeService.list(param))) {
            orderFailRecordService.save(memberId, member.getMobile(), orderDro);
            throw new ErrorException(ExceptionEnum.SEND_ORDER_RECYCLE_STORE_EXCEPTION.getValue());
        }
        if (ListUtil.isNull(stores)) {
            orderFailRecordService.save(memberId, member.getMobile(), orderDro);
            throw new ErrorException(ExceptionEnum.SEND_ORDER_SEND_STORE_EXCEPTION.getValue());
        }
        //库存都足够的仓库
        List<SundayStore> _stores = new ArrayList<>();
        //检测 匹配库存
        List<Integer> statuses = new ArrayList<>();
        statuses.add(2);
        statuses.add(3);
        List<Long> storeIds = stores.stream().map(e -> e.getId()).collect(Collectors.toList());
        param.clear();
        param.put("storeIds", storeIds);
        param.put("statuses", statuses);
        List<SundaySendOrder> orders = super.select(param);
        List<Long> orderIds = orders.stream().map(e -> e.getId()).collect(Collectors.toList());
        List<SundaySendOrderModel> oldOrderModels = new ArrayList<>();
        if (ListUtil.isNotNull(orderIds)) {
            param.clear();
            param.put("orderIds", orderIds);
            oldOrderModels = orderModelMapper.select(param);
        }
        for (SundayStore store : stores) {
            Integer isFull = 1;
            List<SundaySendOrderModel> oldStoreOrderModels = new ArrayList<>();
            if (ListUtil.isNotNull(oldOrderModels)) {
                for (SundaySendOrderModel orderModel : oldOrderModels) {
                    if (orderModel.getStoreId().longValue() == store.getId()) {
                        oldStoreOrderModels.add(orderModel);
                    }
                }
            }
            for (SundaySendOrderModelDro modelDro : orderDro.getModels()) {
                param.clear();
                param.put("storeId", store.getId());
                param.put("modelId", modelDro.getModelId());
                param.put("status", SundayCommonConstants.tray_status_dzl);
                Long storeNum = Long.valueOf(trayMapper.count(param).toString()).longValue();
                //如果现有库存小于订单模板数量  直接break
                if (storeNum < modelDro.getNum()) {
                    isFull = 0;
                    break;
                }
                //如果该仓库存在未配送订单    配送订单模板包含该模板   现有库存减去未配送订单模板的数量小于订单模板数量  也break
                if (ListUtil.isNull(oldStoreOrderModels)) {
                    break;
                }
                Integer oldNum = 0;
                for (SundaySendOrderModel orderModel : oldStoreOrderModels) {
                    if (orderModel.getModelId().longValue() == modelDro.getModelId().longValue()) {
                        oldNum += orderModel.getNum();
                    }
                }
                if (storeNum < oldNum + modelDro.getNum()) {
                    isFull = 0;
                    break;
                }
            }
            if (isFull == 1) {
                _stores.add(store);
            }
        }
        //选择最近的仓库
        SundayStore sendStore = new SundayStore();
        if (ListUtil.isNull(_stores)) {
            orderFailRecordService.save(memberId, member.getMobile(), orderDro);
            throw new ErrorException(ExceptionEnum.SEND_ORDER_STORE_NUM_EXCEPTION.getValue());
        }
        if (_stores.size() == 1) {
            sendStore = _stores.get(0);
        } else {
            Double distence = 100000000.0;
            Map<String, Double> sendMap = MapUtil.getLngAndLat(orderDro.getSendProvince() + orderDro.getSendCity() + orderDro.getSendDistrict() + orderDro.getSendAddress());
            Double longitude = sendMap.get("lng");
            Double latitude = sendMap.get("lat");
            for (SundayStore store : _stores) {
                Double storeDistence = DistanceUtils.GetDistance(longitude, latitude, store.getLongitude(), store.getLatitude());
                if (distence > storeDistence) {
                    sendStore = store;
                    distence = storeDistence;
                }
            }
        }

        //生成订单
        SundaySendOrder order = new SundaySendOrder();
        order.setOrderNo(NumberUtil.generateNumber("SEND"));
        order.setStatus(SundayCommonConstants.send_order_status_dfk);
        order.setServiceId(sendStore.getMemberId());
        order.setServiceName(sendStore.getMemberName());
        order.setServiceMobile(sendStore.getMobile());
        order.setStoreId(sendStore.getId());
        order.setStoreName(sendStore.getName());
        order.setStoreAddress(sendStore.getProvinceName() + sendStore.getCityName() + sendStore.getDistrictName() + sendStore.getAddress());
        order.setMemberId(memberId);
        order.setMemberName(member.getNickName());
        order.setMobile(member.getMobile());
        order.setType(orderDro.getType());
        order.setTime(orderDro.getTime());
        order.setGetTime(orderDro.getGetTime());
        order.setGetType(orderDro.getGetType());
        order.setSendProvinceId(orderDro.getSendProvinceId());
        order.setSendProvince(orderDro.getSendProvince());
        order.setSendCityId(orderDro.getSendCityId());
        order.setSendCity(orderDro.getSendCity());
        order.setSendDistrictId(orderDro.getSendDistrictId());
        order.setSendDistrict(orderDro.getSendDistrict());
        order.setSendAddress(orderDro.getSendAddress());
        order.setRecycleDate(new SimpleDateFormat("yyyy-MM-dd").parse(orderDro.getRecycleDate()));
        order.setRecycleProvinceId(orderDro.getRecycleProvinceId());
        order.setRecycleProvince(orderDro.getRecycleProvince());
        order.setRecycleCityId(orderDro.getRecycleCityId());
        order.setRecycleCity(orderDro.getRecycleCity());
        order.setRecycleDistrictId(orderDro.getRecycleDistrictId());
        order.setRecycleDistrict(orderDro.getRecycleDistrict());
        order.setRecycleAddress(orderDro.getRecycleAddress());
        BigDecimal depositAmount = BigDecimal.ZERO;
        BigDecimal rentAmount = BigDecimal.ZERO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<SundaySendOrderModelDro> models = orderDro.getModels();
        if (ListUtil.isNull(models)) {
            throw new ErrorException(ExceptionEnum.PARAM_NOT_ENOUGH_EXCEPTION.getValue());
        }
        for (SundaySendOrderModelDro modelDro : models) {
            SundayTrayModel model = modelService.find(modelDro.getModelId());
            if (orderDro.getType() == SundayCommonConstants.rent_type_day) {
                rentAmount = rentAmount.add(model.getDayPrice().multiply(new BigDecimal(modelDro.getNum())).multiply(new BigDecimal(orderDro.getTime())));
            } else if (orderDro.getType() == SundayCommonConstants.rent_type_mouth) {
                rentAmount = rentAmount.add(model.getMouthPrice().multiply(new BigDecimal(modelDro.getNum() * 30)).multiply(new BigDecimal(orderDro.getTime())));
            } else if (orderDro.getType() == SundayCommonConstants.rent_type_quarter) {
                rentAmount = rentAmount.add(model.getQuarterPrice().multiply(new BigDecimal(modelDro.getNum() * 90)).multiply(new BigDecimal(orderDro.getTime())));
            }
            if (member.getUserType() == 1) {
                depositAmount = depositAmount.add(model.getDepositPrice().multiply(new BigDecimal(modelDro.getNum())));
            }
        }
        if (member.getUserType() == UserTypeEnum.LEASE.getCode()) {
            order.setPayAmount(depositAmount.add(rentAmount));
            order.setDepositAmount(depositAmount);
        } else {
            order.setPayAmount(rentAmount);
            order.setDepositAmount(BigDecimal.ZERO);
        }
        order.setRentAmount(rentAmount);
        order.setTotalAmount(rentAmount);
        //保存订单
        super.insert(order);
        //保存订单模板
        List<SundaySendOrderModel> orderModels = new ArrayList<>();
        for (SundaySendOrderModelDro modelDro : models) {
            SundayTrayModel model = modelService.find(modelDro.getModelId());
            BigDecimal rentPrice = BigDecimal.ZERO;
            if (orderDro.getType() == SundayCommonConstants.rent_type_day) {
                rentPrice = model.getDayPrice();
            } else if (orderDro.getType() == SundayCommonConstants.rent_type_mouth) {
                rentPrice = model.getMouthPrice();
            } else if (orderDro.getType() == SundayCommonConstants.rent_type_quarter) {
                rentPrice = model.getQuarterPrice();
            }
            SundaySendOrderModel orderModel = new SundaySendOrderModel(order.getId(), sendStore.getId(), modelDro.getModelId(), model.getName(), rentPrice, model.getBuyOutPrice(), model.getDepositPrice(), modelDro.getNum(),modelDro.getNum());
            orderModels.add(orderModel);
        }

        orderModelMapper.batchInsert(orderModels);
        //返回订单信息
        return packageSingleDto(order, null);
    }


    /**
     * 支付订单
     *
     * @param orderId
     * @return
     */
    @Transactional
    public SundaySendOrderDto pay(Long orderId, Long memberId) {
        SundaySendOrder order = super.find(orderId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_dfk);
        checkOrderMember(order, memberId);
        Map<String,Object> param=new HashMap<String,Object>();
        param.put("isDeleted",SundayCommonConstants.NO);
        //检测 匹配库存
        List<Integer> statuses = new ArrayList<>();
        statuses.add(2);
        statuses.add(3);
        param.clear();
        param.put("storeId", order.getStoreId());
        param.put("statuses", statuses);
        List<SundaySendOrder> orders = super.select(param);
        List<Long> orderIds = orders.stream().map(e -> e.getId()).collect(Collectors.toList());
        List<SundaySendOrderModel> oldOrderModels = new ArrayList<>();
        if (ListUtil.isNotNull(orderIds)) {
            param.clear();
            param.put("orderIds", orderIds);
            oldOrderModels = orderModelMapper.select(param);
        }
        param.clear();
        param.put("orderId", orderId);
        List<SundaySendOrderModel> orderModels = orderModelMapper.select(param);
        Integer isFull=1;
        for (SundaySendOrderModel orderModel : orderModels) {
            param.clear();
            param.put("storeId", order.getStoreId());
            param.put("modelId", orderModel.getModelId());
            param.put("status", SundayCommonConstants.tray_status_dzl);
            Long storeNum = Long.valueOf(trayMapper.count(param).toString()).longValue();
            //如果现有库存小于订单模板数量  直接break
            if (storeNum < orderModel.getNum()) {
                isFull = 0;
                break;
            }
            //如果该仓库存在未配送订单    配送订单模板包含该模板   现有库存减去未配送订单模板的数量小于订单模板数量  也break
            if (ListUtil.isNull(oldOrderModels)) {
                break;
            }
            Integer oldNum = 0;
            for (SundaySendOrderModel oldOrderModel : oldOrderModels) {
                if (oldOrderModel.getModelId().longValue() == orderModel.getModelId().longValue()) {
                    oldNum += oldOrderModel.getNum();
                }
            }
            if (storeNum < oldNum + orderModel.getNum()) {
                isFull = 0;
                break;
            }
        }
        if (isFull!=1) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_STORE_NUM_EXCEPTION.getValue());
        }

        SundayWallet wallet = walletService.getWallet(order.getMemberId());
        BigDecimal payAmount=order.getPayAmount();
        SundayCoupon coupon = couponService.getByMemberId(memberId);
        if(coupon!=null&&payAmount.compareTo(coupon.getMoney())==1){
            payAmount=payAmount.subtract(coupon.getMoney());
            //更新优惠券状态
            couponService.updateState(memberId, coupon.getId());
        }
        if (wallet.getMoney().compareTo(payAmount) == -1) {
            throw new ErrorException(ExceptionEnum.MEMBER_WALLET_NO_EXCEPTION.getValue());
        }

        walletRecordService.executeWalletRecord(walletRecordService.createWalletRecord(order.getMemberId(), payAmount, -1
                , WalletRecordEnum.XIAOFEI,order.getOrderNo()));

        order.setStatus(SundayCommonConstants.send_order_status_yfk);
        order.setPayTime(new Date());
        super.update(order);
        return packageSingleDto(order, null);
    }

    /**
     * 取消订单
     *
     * @param orderId
     * @param memberId
     */
    public SundaySendOrderDto cancelOrder(Long orderId, Long memberId) {
        SundaySendOrder order = super.find(orderId);
        checkOrderMember(order, memberId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_dfk);
        order.setStatus(SundayCommonConstants.send_order_status_yqx);
        super.update(order);
        return packageSingleDto(order, null);
    }

    /**
     * 确认订单
     *
     * @param orderId
     * @param serviceId
     */
    public SundaySendOrderDto confirmOrder(Long orderId, Long serviceId) {
        SundaySendOrder order = super.find(orderId);
        checkOrderService(order, serviceId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_yfk);
        order.setStatus(SundayCommonConstants.send_order_status_yjd);
        super.update(order);
        return packageSingleDto(order, null);
    }

    /**
     * 订单发盘 扫码
     *
     * @param orderId
     * @param trayIds
     */
    @Transactional
    public SundaySendOrderDto sendOder(Long orderId, Long serviceId, List<Long> trayIds) {
        SundaySendOrder order = super.find(orderId);
        checkOrderService(order, serviceId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_yjd);
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("isDeleted", SundayCommonConstants.NO);
        param.put("ids", trayIds);
        List<SundayTray> trays = trayMapper.select(param);
        param.clear();
        param.put("orderId", orderId);
        List<SundaySendOrderModel> sendOrderModels = orderModelMapper.select(param);
        List<SundaySendOrderTray> orderTrays = new ArrayList<>();
        for (SundaySendOrderModel orderModel : sendOrderModels) {
            Integer num = 0;
            for (SundayTray tray : trays) {
                if (orderModel.getModelId().longValue() == tray.getModelId().longValue()) {
                    num++;
                    //判断托盘归属服务代理商
                    if (tray.getServiceId().longValue() != serviceId.longValue()) {
                        throw new ErrorException(ExceptionEnum.TRAY_SERVICE_EXCEPTION.getValue());
                    }
                    //判断托盘归属仓库
                    if (tray.getStoreId().longValue() != order.getStoreId().longValue()) {
                        throw new ErrorException(ExceptionEnum.TRAY_STORE_EXCEPTION.getValue());
                    }
                    //判断托盘状态
                    if (tray.getStatus() != SundayCommonConstants.tray_status_dzl) {
                        throw new ErrorException(ExceptionEnum.TRAY_STATUS_EXCEPTION.getValue());
                    }
                    SundaySendOrderTray orderTray = new SundaySendOrderTray(orderId, tray.getId(), SundayCommonConstants.send_order_tray_status_zlz);
                    orderTrays.add(orderTray);
                }
            }
            if (num != orderModel.getNum()) {
                throw new ErrorException(ExceptionEnum.SEND_ORDER_TRAY_NUM_EXCEPTION.getValue());
            }
        }
        //批量新增订单托盘
        orderTrayMapper.batchInsert(orderTrays);

        //批量修改托盘状态
        param.clear();
        param.put("status", SundayCommonConstants.tray_status_zlz);
        trayMapper.batchUpdateFields(param, trayIds);

        order.setSendTime(new Date());
        order.setStatus(SundayCommonConstants.send_order_status_yfp);
        super.update(order);
        return packageSingleDto(order, null);
    }

    /**
     * 扫码校检
     *
     * @param orderId
     * @param serviceId
     * @param modelId
     * @param trayId
     */
    public void scan(Long orderId, Long serviceId, Long modelId, Long trayId) {
        SundaySendOrder order = super.find(orderId);
        SundayTray tray = trayMapper.find(trayId);
        if (tray.getServiceId().longValue() != serviceId.longValue()) {
            throw new ErrorException(ExceptionEnum.TRAY_SERVICE_EXCEPTION.getValue());
        }
        //判断托盘归属仓库
        if (tray.getStoreId().longValue() != order.getStoreId().longValue()) {
            throw new ErrorException(ExceptionEnum.TRAY_STORE_EXCEPTION.getValue());
        }
        //判断托盘状态
        if (tray.getStatus() != SundayCommonConstants.tray_status_dzl) {
            throw new ErrorException(ExceptionEnum.TRAY_STATUS_EXCEPTION.getValue());
        }
        //判断托盘模板
        if (tray.getModelId().longValue() != modelId.longValue()) {
            throw new ErrorException(ExceptionEnum.TRAY_MODEL_EXCEPTION.getValue());
        }

    }


    /**
     * 订单收盘
     *
     * @param orderId
     */
    @Transactional
    public SundaySendOrderDto receiveOder(Long orderId, Long memberId) {
        SundaySendOrder order = super.find(orderId);
        checkOrderMember(order, memberId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_yfp);
        order.setStatus(SundayCommonConstants.send_order_status_ysp);
        Date now = new Date();
        order.setReceiveTime(now);
        //计算回收时间
        Integer type = order.getType();
        Long time = order.getTime();
        Long addNumber = 0l;
        if (type == SundayCommonConstants.rent_type_day) {
            addNumber = time;
        } else if (type == SundayCommonConstants.rent_type_mouth) {
            addNumber = time * 30;
        } else if (type == SundayCommonConstants.rent_type_quarter) {
            addNumber = time * 90;
        }
        Date recycleDate = DatetUtil.updateDate(now, Calendar.DATE, addNumber.intValue());
        order.setRecycleDate(recycleDate);

        super.update(order);
        return packageSingleDto(order, null);
    }

    /**
     * 续费
     *
     * @param orderId
     * @param memberId
     * @param renewTime
     * @param recycleProvinceId
     * @param recycleProvince
     * @param recycleCityId
     * @param recycleCity
     * @param recycleDistrictId
     * @param recycleDistrict
     * @param recycleAddress
     * @return
     */
    public SundaySendOrderDto renew(Long orderId, Long memberId, Long renewTime, Long recycleProvinceId, String recycleProvince, Long recycleCityId,
                                    String recycleCity, Long recycleDistrictId, String recycleDistrict, String recycleAddress) {
        Map<String, Object> param = new HashMap<String, Object>();
        //匹配回收仓库
        param.clear();
        param.put("isDeleted", SundayCommonConstants.NO);
        param.put("cityId", recycleCityId);
        if (ListUtil.isNull(storeService.list(param))) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_RECYCLE_STORE_EXCEPTION.getValue());
        }
        SundaySendOrder order = super.find(orderId);
        checkOrderMember(order, memberId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_ysp);
        order.setRenewTime(renewTime);
        //计算回收时间
        Date receiveDate = order.getRecycleDate();
        Integer type = order.getType();
        Date recycleDate = new Date();
        if (type == SundayCommonConstants.rent_type_day) {
        } else if (type == SundayCommonConstants.rent_type_mouth) {
            renewTime = renewTime * 30;
        } else if (type == SundayCommonConstants.rent_type_quarter) {
            renewTime = renewTime * 90;
        }
        recycleDate = DatetUtil.updateDate(receiveDate, Calendar.DATE, renewTime.intValue());
        //统计续费费用
        param.clear();
        param.put("orderId", orderId);
        List<SundaySendOrderModel> orderModels = orderModelMapper.select(param);
        BigDecimal payAmount = BigDecimal.ZERO;
        for (SundaySendOrderModel orderModel : orderModels) {
            payAmount = payAmount.add(orderModel.getRentPrice().multiply(new BigDecimal(renewTime)).multiply(new BigDecimal(orderModel.getNum())));
        }
        order.setPayAmount(payAmount);
        order.setRentAmount(order.getRentAmount().add(payAmount));
        order.setRecycleDate(recycleDate);
        order.setRecycleProvinceId(recycleProvinceId);
        order.setRecycleProvince(recycleProvince);
        order.setRecycleCityId(recycleCityId);
        order.setRecycleCity(recycleCity);
        order.setRecycleDistrictId(recycleDistrictId);
        order.setRecycleDistrict(recycleDistrict);
        order.setRecycleAddress(recycleAddress);
        return packageSingleDto(order, null);
    }

    /**
     * 续费支付
     *
     * @param orderId
     * @param memberId
     * @param renewTime
     * @param recycleProvinceId
     * @param recycleProvince
     * @param recycleCityId
     * @param recycleCity
     * @param recycleDistrictId
     * @param recycleDistrict
     * @param recycleAddress
     * @return
     */
    @Transactional
    public SundaySendOrderDto renewPay(Long orderId, Long memberId, Long renewTime, Long recycleProvinceId, String recycleProvince, Long recycleCityId,
                                       String recycleCity, Long recycleDistrictId, String recycleDistrict, String recycleAddress) {
        Map<String, Object> param = new HashMap<String, Object>();
        //匹配回收仓库
        param.clear();
        param.put("isDeleted", SundayCommonConstants.NO);
        param.put("cityId", recycleCityId);
        if (ListUtil.isNull(storeService.list(param))) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_RECYCLE_STORE_EXCEPTION.getValue());
        }
        SundaySendOrder order = super.find(orderId);
        checkOrderMember(order, memberId);
        if (order.getStatus() != SundayCommonConstants.send_order_status_ysp
                && order.getStatus() != SundayCommonConstants.send_order_status_ydq) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_STATUS_EXCEPTION.getValue());
        }
        param.clear();
        param.put("orderId", orderId);
        List<SundaySendOrderModel> orderModels = orderModelMapper.select(param);
        //统计时间  天数
        Date receiveDate = order.getReceiveTime();
        Date now = new Date();
        long diff = now.getTime() - receiveDate.getTime();
        long days = diff / (1000 * 60 * 60 * 24);
        //实际使用天数
        days = days <= 0 ? 1 : days;
        //计算回收时间
        Date addDate = order.getRecycleDate();
        Integer type = order.getType();
        Date recycleDate = new Date();
        order.setRenewTime(renewTime);
        if (type == SundayCommonConstants.rent_type_day) {
        } else if (type == SundayCommonConstants.rent_type_mouth) {
            renewTime = renewTime * 30;
        } else if (type == SundayCommonConstants.rent_type_quarter) {
            renewTime = renewTime * 90;
        }
        //实际使用费用
        BigDecimal realAmount = BigDecimal.ZERO;
        BigDecimal oneAmount = BigDecimal.ZERO;
        //续费费用
        BigDecimal payAmount = BigDecimal.ZERO;
        for (SundaySendOrderModel orderModel : orderModels) {
            realAmount = realAmount.add(orderModel.getRentPrice().multiply(new BigDecimal(orderModel.getNum())).multiply(new BigDecimal(days)));
            oneAmount = oneAmount.add(orderModel.getRentPrice().multiply(new BigDecimal(orderModel.getNum())));
            payAmount = payAmount.add(orderModel.getRentPrice().multiply(new BigDecimal(renewTime)).multiply(new BigDecimal(orderModel.getNum())));
        }

        // 判断最少要续费多少天   可能存在欠费情况下续费
        BigDecimal totalAmount = order.getTotalAmount();
        if (realAmount.compareTo(totalAmount) == 1) {
            BigDecimal chaAmount = realAmount.subtract(totalAmount);
            BigDecimal chaDay = chaAmount.divide(oneAmount);
            if (chaDay.compareTo(new BigDecimal(renewTime)) == 1) {
                throw new ErrorException(ExceptionEnum.SEND_ORDER_RENEW_NUM_EXCEPTION.getValue());
            }
        }
        recycleDate = DatetUtil.updateDate(addDate, Calendar.DATE, renewTime.intValue());

        SundayWallet wallet = walletService.getWallet(order.getMemberId());
        if (wallet.getMoney().compareTo(payAmount) == -1) {
            throw new ErrorException(ExceptionEnum.MEMBER_WALLET_NO_EXCEPTION.getValue());
        }

        walletRecordService.executeWalletRecord(walletRecordService.createWalletRecord(order.getMemberId(), payAmount, -1
                , WalletRecordEnum.XUZU, order.getOrderNo()));
        order.setStatus(SundayCommonConstants.send_order_status_ysp);
        order.setPayAmount(payAmount);
        order.setRentAmount(order.getRentAmount().add(payAmount));
        order.setTotalAmount(order.getTotalAmount().add(payAmount));
        order.setRecycleDate(recycleDate);
        order.setRecycleProvinceId(recycleProvinceId);
        order.setRecycleProvince(recycleProvince);
        order.setRecycleCityId(recycleCityId);
        order.setRecycleCity(recycleCity);
        order.setRecycleDistrictId(recycleDistrictId);
        order.setRecycleDistrict(recycleDistrict);
        order.setRecycleAddress(recycleAddress);

        super.update(order);
        return packageSingleDto(order, null);

    }

    /**
     * 买断
     *
     * @param orderId
     * @param memberId
     * @return
     */
    public SundaySendOrderDto buyOut(Long orderId, Long memberId) {
        SundaySendOrder order = super.find(orderId);
        checkOrderMember(order, memberId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_ysp);
        Map<String, Object> param = new HashMap<String, Object>();
        //统计续费费用
        param.clear();
        param.put("orderId", orderId);
        List<SundaySendOrderModel> orderModels = orderModelMapper.select(param);
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal payAmount = BigDecimal.ZERO;
        for (SundaySendOrderModel orderModel : orderModels) {
            totalAmount = totalAmount.add(orderModel.getBuyOutPrice().multiply(new BigDecimal(orderModel.getNum())));
        }
        BigDecimal depositAmount = BigDecimal.ZERO;
        if (order.getDepositAmount() != null) {
            depositAmount = order.getDepositAmount();
        }
        payAmount = totalAmount.subtract(depositAmount);
        order.setPayAmount(payAmount);
        order.setTotalAmount(totalAmount);
        return packageSingleDto(order, null);
    }

    /**
     * 买断付款
     *
     * @param orderId
     * @param memberId
     * @return
     */
    @Transactional
    public SundaySendOrderDto buyOutPay(Long orderId, Long memberId) {
        SundaySendOrder order = super.find(orderId);
        checkOrderMember(order, memberId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_ysp);
        Map<String, Object> param = new HashMap<String, Object>();
        //统计买断费用
        param.clear();
        param.put("orderId", orderId);
        List<SundaySendOrderModel> orderModels = orderModelMapper.select(param);
        List<SundaySendOrderTray> orderTrays = orderTrayMapper.select(param);
        BigDecimal payAmount = BigDecimal.ZERO;
        Integer trayNum = 0;
        Integer modelNum = 0;
        //统计时间  天数
        Date receiveDate = order.getReceiveTime();
        Date now = new Date();
        long diff = now.getTime() - receiveDate.getTime();
        long days = diff / (1000 * 60 * 60 * 24);
        //实际使用天数
        days = days <= 0 ? 1 : days;
        //实际使用费用
        BigDecimal realAmount = BigDecimal.ZERO;
        for (SundaySendOrderModel orderModel : orderModels) {
            modelNum += orderModel.getNum();
            payAmount = payAmount.add(orderModel.getBuyOutPrice().multiply(new BigDecimal(orderModel.getNum())));
            realAmount = realAmount.add(orderModel.getRentPrice().multiply(new BigDecimal(orderModel.getNum()).multiply(new BigDecimal(days))));
        }
        List<Long> trayIds = new ArrayList<>();
        List<Long> orderTrayIds = new ArrayList<>();
        for (SundaySendOrderTray orderTray : orderTrays) {
            if (orderTray.getStatus() == SundayCommonConstants.send_order_tray_status_zlz) {
                trayNum++;
                trayIds.add(orderTray.getTrayId());
                orderTrayIds.add(orderTray.getId());
            }
        }
        if (trayNum != modelNum) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_BUYOUT_NUM_EXCEPTION.getValue());
        }

        SundayWallet wallet = walletService.getWallet(order.getMemberId());
        if (wallet.getMoney().compareTo(payAmount) == -1) {
            throw new ErrorException(ExceptionEnum.MEMBER_WALLET_NO_EXCEPTION.getValue());
        }

        walletRecordService.executeWalletRecord(walletRecordService.createWalletRecord(order.getMemberId(), payAmount, -1
                , WalletRecordEnum.MAIDUAN, order.getOrderNo()));
        //返回租金
        BigDecimal totalAmount = order.getTotalAmount();
        BigDecimal chaAmount = totalAmount.subtract(realAmount);
        //如果有差值大于0  并且订单类型为日租  则退租金
        if (chaAmount.compareTo(BigDecimal.ZERO) == 1 && order.getType() == SundayCommonConstants.rent_type_day) {
            walletRecordService.executeWalletRecord(walletRecordService.createWalletRecord(order.getMemberId(), chaAmount, 1
                     , WalletRecordEnum.ZUJINTUHUAN,order.getOrderNo()));
        }
        //如果差值小于0   则扣押金
        BigDecimal depositAmount = BigDecimal.ZERO;
        if (order.getDepositAmount() != null) {
            depositAmount = order.getDepositAmount();
        }
        if (chaAmount.compareTo(BigDecimal.ZERO) == -1) {
            depositAmount = depositAmount.subtract(chaAmount);
        }
        if (depositAmount.compareTo(BigDecimal.ZERO) == 1) {
            //返回押金 并且扣除租金或者返回租金
            walletRecordService.executeWalletRecord(walletRecordService.createWalletRecord(order.getMemberId(), depositAmount, 1
                    , WalletRecordEnum.YAJINTUIHUAN, order.getOrderNo()));
        }


        //批量更新状态
        param.clear();
        param.put("status", SundayCommonConstants.tray_status_ymd);
        trayMapper.batchUpdateFields(param, trayIds);
        param.clear();
        param.put("status", SundayCommonConstants.send_order_tray_status_ymd);
        orderTrayMapper.batchUpdateFields(param, orderTrayIds);

        order.setRentAmount(realAmount.add(payAmount));
        order.setStatus(SundayCommonConstants.send_order_status_ymd);
        super.update(order);
        return packageSingleDto(order, null);
    }

    /**
     * 冻结回收
     *
     * @param orderId
     * @param serviceId
     * @param trayIds
     * @return
     */
    public SundaySendOrderDto freezeBack(Long orderId, Long serviceId, List<Long> trayIds) {
        SundaySendOrder order = super.find(orderId);
        checkOrderService(order, serviceId);
        checkOrderStatus(order, SundayCommonConstants.send_order_status_ydj);
        Map<String, Object> param = new HashMap<String, Object>();
        if (ListUtil.isNotNull(trayIds)) {
            //批量修改托盘状态
            param.clear();
            param.put("status", SundayCommonConstants.tray_status_zlz);
            param.put("serviceId", serviceId);
            trayMapper.batchUpdateFields(param, trayIds);
        }
        param.clear();
        param.put("orderId", orderId);
        param.put("status", SundayCommonConstants.send_order_tray_status_zlz);
        List<SundaySendOrderTray> orderTrays = orderTrayMapper.select(param);
        List<Long> orderTrayIds = orderTrays.stream().map(e -> e.getId()).collect(Collectors.toList());
        List<Long> _orderTrayIds = new ArrayList<>();
        //剔除回收的托盘id   剩余未回收的报废
        for (Long orderTrayId : orderTrayIds) {
            Integer isAdd = 1;
            if (ListUtil.isNotNull(trayIds)) {
                for (Long trayId : trayIds) {
                    if (orderTrayId.longValue() == trayId.longValue()) {
                        isAdd = 0;
                        break;
                    }
                }
            }
            if (isAdd == 1) {
                _orderTrayIds.add(orderTrayId);
            }
        }
        param.clear();
        param.put("status", SundayCommonConstants.tray_status_ysh);
        trayMapper.batchUpdateFields(param, _orderTrayIds);

        order.setStatus(SundayCommonConstants.send_order_status_ysh);
        super.update(order);

        return packageSingleDto(order, null);
    }


    /**
     * 组装单个
     *
     * @param order
     * @return
     */
    private SundaySendOrderDto packageSingleDto(SundaySendOrder order, List<SundaySendOrderModel> models) {
        SundaySendOrderDto dto = new SundaySendOrderDto();
        if (ListUtil.isNull(models)) {
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("orderId", order.getId());
            models = new ArrayList<SundaySendOrderModel>();
            for (SundaySendOrderModel orderModel : orderModelMapper.select(param)) {
                if (orderModel.getOrderId().longValue() == order.getId()) {
                    models.add(orderModel);
                }
            }
        }
        BeanUtils.copyProperties(order, dto);
        dto.setTotalAmount(order.getTotalAmount().setScale(2,BigDecimal.ROUND_DOWN ));
        dto.setDepositAmount(order.getDepositAmount().setScale(2,BigDecimal.ROUND_DOWN ));
        dto.setPayAmount(order.getPayAmount().setScale(2,BigDecimal.ROUND_DOWN ));
        dto.setModels(orderModelService.packageMultiDto(models));
        return dto;
    }


    public List<SundaySendOrderDto> packageMultiDto(List<SundaySendOrder> orders) {
        List<SundaySendOrderDto> dtos = new ArrayList<>();
        List<Long> orderIds = new ArrayList<>();
        for (SundaySendOrder order : orders) {
            orderIds.add(order.getId());
        }
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("orderIds", orderIds);
        List<SundaySendOrderModel> orderModels = orderModelMapper.select(param);
        for (SundaySendOrder order : orders) {
            List<SundaySendOrderModel> models = new ArrayList<SundaySendOrderModel>();
            for (SundaySendOrderModel orderModel : orderModels) {
                if (orderModel.getOrderId().longValue() == order.getId()) {
                    models.add(orderModel);
                }
            }
            dtos.add(packageSingleDto(order, models));
        }
        return dtos;
    }

    /**
     * 核对订单状态
     *
     * @param order
     * @param orderStatus
     * @return
     */
    public SundaySendOrder checkOrderStatus(SundaySendOrder order, Integer orderStatus) {
        if (order.getStatus() != orderStatus) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_STATUS_EXCEPTION.getValue());
        }
        return order;
    }

    /**
     * 核对供应商
     *
     * @param order
     * @param serviceId
     * @return
     */
    public SundaySendOrder checkOrderService(SundaySendOrder order, Long serviceId) {
        if (order.getServiceId().longValue() != serviceId.longValue()) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_SERVICE_EXCEPTION.getValue());
        }
        return order;
    }

    /**
     * 核对用户
     *
     * @param order
     * @param memberId
     * @return
     */
    public SundaySendOrder checkOrderMember(SundaySendOrder order, Long memberId) {
        if (order.getMemberId().longValue() != memberId.longValue()) {
            throw new ErrorException(ExceptionEnum.SEND_ORDER_MEMBER_EXCEPTION.getValue());
        }
        return order;
    }


}
